package com.linkai.JUC._02_pc;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description: JUC 中的 Condition 的优点
 *               实现功能：A执行完调用B，B执行完调用C，C执行完调用A（顺序执行）
 * @Author: 林凯
 * @Date: 2021/10/23 20:16
 */
public class _03_ProducerJUC02_Condition {
    public static void main(String[] args) {
        Data03 data03 = new Data03();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                data03.printA();
            }
        }, "A").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                data03.printB();
            }
        }, "B").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                data03.printC();
            }
        }, "C").start();
    }
}

// 资源类
class Data03 {
    private Lock reentrantLock = new ReentrantLock();
    // 通过多个 Condition 来精确控制顺序
    private Condition condition1 = reentrantLock.newCondition();
    private Condition condition2 = reentrantLock.newCondition();
    private Condition condition3 = reentrantLock.newCondition();
    private int number = 1;     // 1-A  2-B  3-C


    public void printA() {
        reentrantLock.lock();
        try {
            // 业务 -> 判断 -> 执行 -> 通知
            while (number != 1) {
                // 等待
                condition1.await();
            }
            System.out.println(Thread.currentThread().getName() + "AAAAA");
            number = 2;
            condition2.signal();
            // 唤醒，唤醒指定的人：B
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
        }
    }

    public void printB() {
        reentrantLock.lock();
        try {
            // 业务 -> 判断 -> 执行 -> 通知
            while (number != 2) {
                // 等待，B等待，这里设置 condition2.await(); 到时候唤醒 B 就是 condition2.signal();
                condition2.await();
            }
            System.out.println(Thread.currentThread().getName() + "BBBBB");
            number = 3;
            // 唤醒C
            condition3.signal();
            // 唤醒，唤醒指定的人：C
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
        }


    }
    public void printC() {
        reentrantLock.lock();
        try {
            // 业务 -> 判断 -> 执行 -> 通知
            while (number != 3) {
                // 等待，B等待，这里设置 condition2.await(); 到时候唤醒 B 就是 condition2.signal();
                condition3.await();
            }
            System.out.println(Thread.currentThread().getName() + "CCCCC");
            number = 1;
            // 唤醒C
            condition1.signal();
            // 唤醒，唤醒指定的人：C
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
        }
    }
}
